package com.yelink.metrics.core.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.yelink.metrics.core.MetricsUtils;
import com.yelink.metrics.core.constant.annotations.MetricsColumn;
import com.yelink.metrics.core.constant.annotations.MetricsInfo;
import lombok.Data;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.stream.Collectors;

/**
 * @author idea
 */
@Data
public abstract class BaseMetricsEntity {
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @TableId(value = "id", type = IdType.AUTO)
    @MetricsColumn(comment = "主键")
    private Integer id;

    @TableField(value = "uni_code")
    @MetricsColumn(comment = "唯一标识")
    private String uniCode;

    /**
     * 最近更新时间
     */
    @TableField(value = "time")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @MetricsColumn(comment = "最近执行时间")
    private Date time;
    /**
     * 获取唯一标识： 由用户定义的唯一索引组成
     * <p>注意移动字段位置可能导致拼接顺序变动</p>
     * @return 唯一标识
     */
    public String getUniCode() {
        Class<?> clazz = this.getClass();
        MetricsInfo metricsInfo = clazz.getAnnotation(MetricsInfo.class);
        boolean diy = metricsInfo != null && metricsInfo.diyUniCode();
        return Arrays.stream(clazz.getDeclaredFields())
                .filter(e -> diy? MetricsUtils.checkIsDimensionDiy(e): MetricsUtils.checkIsDimension(e))
                .map(field -> {
                    field.setAccessible(true);
                    try {
                        Object o = field.get(this);
                        return formatVal(o);
                    } catch (IllegalAccessException e) {
                        return null;
                    }
                }).collect(Collectors.joining("_"));
    }


    /**
     * 格式化 字段值
     * @param o 字段值
     * @return 格式化后的
     */
    public static String formatVal(Object o) {
        if(o == null) {
            return null;
        }
        if (o instanceof LocalDateTime) {
            return ((LocalDateTime) o).format(FORMATTER);
        } else if (o instanceof LocalDate) {
            // 补足时间为 00:00:00
            return ((LocalDate) o).atStartOfDay().format(FORMATTER);
        } else if (o instanceof Date) {
            return ((Date) o).toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime()
                    .format(FORMATTER);
        } else {
            return o.toString();
        }
    }

    public static String buildUniCodeFormat(Class<?> clazz) {
        MetricsInfo metricsInfo = clazz.getAnnotation(MetricsInfo.class);
        boolean diy = metricsInfo != null && metricsInfo.diyUniCode();
        return Arrays.stream(clazz.getDeclaredFields())
                .filter(e -> diy? MetricsUtils.checkIsDimensionDiy(e): MetricsUtils.checkIsDimension(e))
                .map(e -> String.format("${%s}", e.getName())).collect(Collectors.joining("_"));
    }
}
